home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1995 April / Internet Tools.iso / mail / listserv / sco / proclist.mmdf.sco.c.Z / proclist.mmdf.sco.c
Encoding:
C/C++ Source or Header  |  1992-07-01  |  6.4 KB  |  231 lines

  1. /* @(#) proclist    -- dispatch listserv requests to catmail
  2.  *
  3.  *    Due to a bug in SCO Unix's MMDF, we can't use listserv's
  4.  *    /usr/server/catmail program within an aliased pipe.  For
  5.  *    some odd reason, MMDF strips the first internet header line
  6.  *    in pipes.  Listserv absolutely requires that this
  7.  *    "From address Date" header line be present.
  8.  *
  9.  *    The work-around is to force incoming mail for listserv and
  10.  *    mailing lists to land in physical mailboxes belonging to
  11.  *    pseudo-users.  This will require creating /etc/passwd users
  12.  *    to receive requests for the listserver and each mailing list.
  13.  *    The names are insignificant and may be aliased in
  14.  *    /usr/mmdf/table/alias.list.  You will need one for 'listserv'
  15.  *    and one for each supported mailing list.
  16.  *
  17.  *    This program, intended to be run either as a crontab entry or
  18.  *    interactively, will look for mail for the selected user and,
  19.  *    if the mail file exists, will strip the MMDF Ctrl-A separators
  20.  *    (which confuse listserv) from each message and pipe them through
  21.  *    /usr/server/catmail using the arguments specified on the command
  22.  *    line.  See the server.nr dox for more information about catmail
  23.  *    arguments.
  24.  *
  25.  *    Finally, we will launch the server program to process incoming
  26.  *    mail.  The 'serverd' field in /usr/server/config file must
  27.  *    specify '-1' to tell the server not to load itself into the
  28.  *    background.  The server will only run if we have found mail and
  29.  *    successfully piped it through catmail.
  30.  *
  31.  *    Usage:    proclist <user> <catmail_args>
  32.  *     i.e.:    proclist listserv -r -f
  33.  *        proclist mcycle -L MCYCLE -f
  34.  *
  35.  *    Author: Steve Manes    manes@magpie.nycenet.edu
  36.  *
  37.  *        Manes and Associates, NYC
  38.  *        July 1, 1992
  39.  * 
  40.  *    Developed for Learning Link, Linknet, Inc.
  41.  *    Public Broadcasting System, NYC
  42.  */
  43.  
  44. #include <stdio.h>
  45. #include <sys/types.h>
  46. #include <unistd.h>
  47. #include <sys/stat.h>
  48. #include <fcntl.h>
  49. #include <varargs.h>
  50. #include <time.h>
  51.  
  52. #define    SPOOLDIR    "/usr/spool/mail"
  53. #define    CATMAIL        "/usr/server/catmail"
  54. #define    SERVER        "/usr/server/start"
  55. #define    LOGFILE        "/usr/spool/listserv/errlog"
  56. #define    CTRL_A        1
  57. #define    FILENAMESIZE    128
  58. #define    RECBUFSIZE    512
  59. #define    MAXRETRIES    10
  60. #define    ERROR        -1
  61.  
  62. void    usage();
  63. void    log();
  64.  
  65. void    main( int argc, char *argv[] )
  66. {
  67.     FILE    *ofd, *catfd;
  68.     int    ifd, i, sz, count;
  69.     struct    stat Stat;
  70.     struct    flock Flock;
  71.     int    try;
  72.     
  73.     char    buf[RECBUFSIZE+1],
  74.         mailfile[FILENAMESIZE+1],
  75.         workfile[FILENAMESIZE+1],
  76.         catfile[FILENAMESIZE+1];
  77.     
  78.     if (argc < 2)
  79.         usage();
  80.  
  81.     /* make sure that we have read/write access to
  82.      * the user's mailfile */
  83.     sprintf(mailfile, "%s/%s", SPOOLDIR, argv[1]);
  84.     if (access(mailfile, F_OK)) {
  85.         log("Mailfile %s not found!\n", mailfile);
  86.         exit(1);
  87.     }
  88.     else if (access(mailfile, R_OK)) {
  89.         log("Mailfile %s: no read permission!\n", mailfile);
  90.         exit(1);
  91.     }
  92.     else if (access(mailfile, W_OK)) {
  93.         log("Mailfile %s: no write permission!\n", mailfile);
  94.         exit(1);
  95.     }
  96.     else if (stat(mailfile, &Stat)) {
  97.         log("Can't stat %s!\n", mailfile);
  98.         exit(1);
  99.     }
  100.     else if (Stat.st_size < 1) {
  101.         log("%s has no mail for me\n", mailfile);
  102.         exit(1);
  103.     }
  104.     
  105.     /* make sure we can open a pipe to listserv's catmail */
  106.     strcpy(catfile, CATMAIL);
  107.     if (access(catfile, X_OK)) {
  108.         log("Can't execute %s\n", catfile);
  109.         exit( 1 );
  110.     }
  111.     for (i=2; i < argc; i++) {    /* append catmail's command line */
  112.         strcat(catfile, " ");
  113.         strcat(catfile, argv[i]);
  114.     }
  115.  
  116.     /* open the mailfile */
  117.     if ((ifd = open(mailfile, O_RDWR)) == ERROR) {
  118.         log("Can't open input %s\n", mailfile);
  119.         exit(1);
  120.     }
  121.     
  122.     /* lock the mailfile from other processes */
  123.     Flock.l_type = F_WRLCK;            /* write-lock only */
  124.     Flock.l_whence = 0L;            /* from beginning of file */
  125.     Flock.l_start = Flock.l_len = 0L;    /* till the end of file */
  126.  
  127.     /* wait twenty seconds to assert a lock */    
  128.     for (try=0; fcntl(ifd, F_SETLK, &Flock) < 0; try++) {
  129.         if (try == MAXRETRIES) {
  130.             log("Can't lock %s\n", mailfile);
  131.             exit(1);
  132.         }
  133.         sleep(2);        /* wait a coupla seconds... */
  134.     }
  135.         
  136.     /* copy mail file to tmp directory for processing */
  137.     sprintf(workfile, "/tmp/PROCLIST.%d", getpid());
  138.     if ((ofd = fopen(workfile, "w+")) == NULL) {
  139.         log("Can't open output %s\n", workfile);
  140.         exit(1);
  141.     }
  142.     while( (sz = read(ifd, buf, RECBUFSIZE)) > 0)
  143.         fwrite(buf, sizeof(char), sz, ofd);
  144.     
  145.     chsize(ifd, 0L);        /* make file empty */
  146.  
  147.     /* unlock the file */    
  148.     Flock.l_type = F_UNLCK;
  149.     Flock.l_whence = 0L;            /* from beginning of file */
  150.     Flock.l_start = Flock.l_len = 0L;    /* till the end of file */
  151.     fcntl(ifd, F_SETLK, &Flock);
  152.     close(ifd);                /* and close it */
  153.         
  154.     /* At this point, we have the user's mailfile copied to /tmp,
  155.      * where we can operate on it without being disturbed by other
  156.      * processes.  We also zapped his SPOOLDIR mail so it's ready
  157.      * to accept mail without us getting in the way. */
  158.      
  159.     rewind(ofd);            /* back to the top */
  160.     catfd = NULL;
  161.     count = 0;
  162.     
  163.     /* page through the mail file, piping each message to catmail */
  164.     while (fgets(buf, RECBUFSIZE, ofd) != NULL) {
  165.     
  166.         /* MMDF's message separators make this easy, but
  167.          * listserv will choke on 'em so stifle 'em */
  168.         if (buf[0] == CTRL_A) {
  169.             if (catfd != NULL) {
  170.                 pclose(catfd);
  171.                 catfd = NULL;
  172.             }
  173.             continue;
  174.         }
  175.         if (catfd == NULL) {
  176.             if ((catfd = popen(catfile, "w")) == NULL) {
  177.                 log("Can't open pipe to %s\n", buf);
  178.                 exit( 1 );
  179.             }
  180.             count++;
  181.         }
  182.         fputs(buf, catfd);
  183.     }
  184.     
  185.     if (catfd != NULL)
  186.         pclose(catfd);        /* close the CATMAIL pipe */
  187.     fclose(ofd);            /* close the /tmp workfile... */
  188.     unlink(workfile);        /*  and delete it. */
  189.     
  190.     log("%d message(s) processed\n", count);
  191.     if (execl(SERVER, "start", "-c", NULL) == ERROR)
  192.         perror(SERVER);
  193. }
  194.  
  195. /*---[ usage ]-------------------------------------------------------------
  196.     show program arguments    
  197.  --------------------------------------------------------------------------*/
  198. void    usage()
  199. {
  200.     fprintf(stderr, "usage: proclist <user> <catmail arguments>\n");
  201.     exit( 1 );
  202. }
  203.  
  204. /*---[ log ]---------------------------------------------------------------
  205.     log error messages to file LOGFILE
  206.     if LOGFILE, doesn't exist, don't create it
  207.  --------------------------------------------------------------------------*/
  208. void    log( va_alist )
  209. va_dcl
  210. {
  211.     va_list    args;
  212.     char    *fmt, tbuf[20];
  213.     FILE    *fd;
  214.     time_t    t;
  215.     
  216.     if ( !access(LOGFILE, W_OK) ) {        /* is there a logfile? */
  217.         va_start(args);    
  218.         fmt = va_arg(args, char *);
  219.         time(&t);
  220.         if ((fd = fopen(LOGFILE, "a")) != NULL) {
  221.             strftime(tbuf, 20, "%m/%d %H:%M:%S  ", localtime(&t));
  222.             fprintf(fd, "%s", tbuf);
  223.             vfprintf(fd, fmt, args);
  224.             va_end(args);
  225.             fclose(fd);
  226.         }
  227.     }
  228. }
  229.  
  230. /* END PROCLIST */
  231.